#!/bin/zsh
# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# 使用说明

# 1、各种补全：路径补全、命令补全，命令参数补全，插件内容补全等等。
## 触发补全只需要按一下或两下 tab 键，补全项可以使用 ctrl+n/p/f/b上下左右切换。
## 例1: 你想杀掉 java 的进程，只需要输入 kill java + tab键，如果只有一个 java 进程，zsh 会自动替换为进程的 pid，如果有多个则会出现选择项供你选择。
## 例2: ssh + 空格 + 两个tab键，zsh会列出所有访问过的主机和用户名进行补全

# 2、智能跳转，安装了autojump之后，zsh 会自动记录你访问过的目录，通过 j + 目录名 可以直接进行目录跳转，而且目录名支持模糊匹配和自动补全
## 例1: 如访问过hadoop-1.0.0目录，输入j hado 即可正确跳转。
## 例2: j –stat 可以看你的历史路径库。

# 3、目录浏览和跳转：输入 d，即可列出你在这个会话里访问的目录列表，输入列表前的序号，即可直接跳转。

# 4、在当前目录下输入 .. 或 … ，或直接输入当前目录名都可以跳转，你甚至不再需要输入 cd 命令了。

#> 参考资料
# - [终极 Shell——ZSH](https://zhuanlan.zhihu.com/p/19556676)
# - [为什么说 zsh 是 shell 中的极品？](https://www.zhihu.com/question/21418449)
# - [Mac安装oh my zsh插件autojump、zsh-syntax-highlighting、zsh-autosuggestion](https://www.jianshu.com/p/bd9ea233f933?utm_campaign=haruki)
# - [快速安装oh-my-zsh的插件zsh-syntax-highlighting 语法高亮](https://blog.csdn.net/shenhonglei1234/article/details/106676481)

# 关闭每天会在第一次打开时进行自动更新检测（需要开启时注释掉）
DISABLE_AUTO_UPDATE="true" 

# 手动更新呢？请执行下面的命令即可：
# upgrade_oh_my_zsh 或 omz update
# 当然也可以通过下面的方式来进行检查更新：
# zsh ~/.oh-my-zsh/tools/check_for_upgrade.sh

# glabal_github_proxy_url="https://github.moeyy.xyz/"
# glabal_github_proxy_url="https://gitapi.simplehac.top/"
glabal_github_proxy_url=""

# 解决zsh:zsh: command not found:
# source ~/.bash_profile

# colorize man pages / 命令手册颜色主题
export LESS=-R 
export LESS_TERMCAP_mb=$'\e[1;31m'
export LESS_TERMCAP_md=$'\e[1;31m'
export LESS_TERMCAP_me=$'\e[0m'
export LESS_TERMCAP_se=$'\e[0m'
export LESS_TERMCAP_so=$'\e[1;44;33m'
export LESS_TERMCAP_ue=$'\e[0m'
export LESS_TERMCAP_us=$'\e[1;4;32m'

# # 当存在nvim或vim时，使用man时用其打开
# if [ -x "$(which nvim)" ]; then
#   export MANPAGER='nvim +Man!'
# elif [ -x "$(which vim)" ]; then
#   export MANPAGER='vim +Man!'
# fi

export PATH=/opt/local/bin:$PATH
export PATH=/opt/local/sbin:$PATH

# Java
# JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
PATH=$JAVA_HOME/bin:$PATH:.
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export PATH
export CLASSPATH  

# 解决zsh:zsh: command not found fzf:
PATH=$PATH:$HOME/bin:$HOME/Tools:$HOME/.local/bin
# 解决 cargo 安装的软件找不到
PATH=$PATH:$HOME/.cargo/bin
export PATH

# [git-remote-gcrypt](https://git.spwhitton.name/git-remote-gcrypt)
# 添加以下环境变量在你的cli：(否则会出错)
export GPG_TTY=$(tty)
export PATH=$GPG_TTY:$PATH:.

# python
PY_VERSION=`python3 -V 2>&1|awk '{print $2}'|awk -F '.' '{print $1"."$2}'`
# export PATH=${PATH}:$HOME/Library/Python/$PY_VERSION/lib/python/site-packages
# export PATH=${PATH}:/Library/Python/$PY_VERSION/site-packages
export PATH=${PATH}:$HOME/Library/Python/$PY_VERSION/bin



# 添加HBuilderX的cli命令
# 方法1：添加环境变量
export HX_HOME=/Applications/HBuilderX.app/Contents/MacOS/
export PATH=$HX_HOME:$PATH:.


# 添加calibre（电子书）命令行工具
# export CAKLIBRE_HOME="/Applications/calibre.app/Contents/console.app/Contents/MacOS"
export CAKLIBRE_HOME="/Applications/calibre.app/Contents/MacOS"
export PATH=$CAKLIBRE_HOME:$PATH:.

# node版本管理器nvm
export NVM_DIR="$HOME/.nvm"
[ -s "/usr/local/opt/nvm/nvm.sh" ] && \. "/usr/local/opt/nvm/nvm.sh"  # This loads nvm
[ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/usr/local/opt/nvm/etc/bash_completion.d/nvm"  # This loads nvm bash_completion

#方法2：创建别名
# shell类型：zsh
#echo "alias cli='/Applications/HBuilderX.app/Contents/MacOS/cli'" >> ~/.zshrc && source ~/.zshrc

# lf图标载入
[ -f ~/.config/lf/icons ] && source ~/.config/lf/icons

# fzf脚本载入
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh

# 添加相应命令所在路径到环境变量中 
# 先查找 find / -name "命令工具名"
# export PATH=~/.npm-global/bin:${PATH}:/usr/local/bin

# john
john_jumbo="/usr/local/Cellar/john-jumbo/1.9.0_1/share/john"
# export PATH="/usr/local/Cellar/john-jumbo/1.9.0_1/share/john:$PATH"
export PATH="$john_jumbo:$PATH"

# ruby
# If you need to have ruby first in your PATH run:
#   echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
# For compilers to find ruby you may need to set:
#   export LDFLAGS="-L/usr/local/opt/ruby/lib"
#   export CPPFLAGS="-I/usr/local/opt/ruby/include"
export PATH="/usr/local/opt/ruby/bin:$PATH"

# 检查与安装 oh-my-zsh   Install oh-my-zsh if not exist
OHMYZSH="$HOME/.oh-my-zsh"
if [ ! -d "$OHMYZSH" ]; then
  echo "Installing oh-my-zsh ..."
  #URL="https://github.moeyy.xyz/https://github.com/robbyrussell/oh-my-zsh.git"
  URL="${glabal_github_proxy_url}https://github.com/robbyrussell/oh-my-zsh.git"
  Echo "[INFO] "
  if [ -x "$(which git)" ]; then
    echo "[INFO] git 克隆 oh-my-zsh 到 ~/.oh-my-zsh"
    echo "[INFO] git clone --depth 1 $URL $OHMYZSH"
    git clone --depth 1 "$URL" "$OHMYZSH"
  else
    echo "ERROR: please install git  before installation !!"
    exit
  fi
  if [ ! $? -eq 0 ]; then
    echo ""
    echo "ERROR: downloading oh-my-zsh ($URL) failed !!"
    exit
  fi;
  echo "move $TMPFILE to $ANTIGEN"
fi

# Path to your oh-my-zsh installation.
export ZSH="${HOME}/.oh-my-zsh"

# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
ZSH_THEME="clean" # set by `omz`

# 插件
# 安装插件 zsh-syntax-highlighting 
# git clone https://hub.fastgit.org/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
# 安装插件 zsh-syntax-highlighting 
# git clone https://hub.fastgit.org/zsh-users/zsh-syntax-highlighting $ZSH_CUSTOM/plugins/zsh-syntax-highlighting

if [[ ! -d ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions ]]; then
    git clone --depth=1 "${glabal_github_proxy_url}https://github.com/zsh-users/zsh-autosuggestions"  ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
fi

if [[ ! -d ~/.oh-my-zsh/custom/plugins/zsh-history-substring-search ]]; then
    git clone --depth=1 "${glabal_github_proxy_url}https://github.com/zsh-users/zsh-history-substring-search"  ~/.oh-my-zsh/custom/plugins/zsh-history-substring-search
fi 

if [[ ! -d ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting ]]; then
    git clone --depth=1 "${glabal_github_proxy_url}https://github.com/zsh-users/zsh-syntax-highlighting"  ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
fi 

# if [[ ! -d ~/.oh-my-zsh/custom/plugins/zsh-vi-mode ]]; then
#      git clone --depth=1 "${glabal_github_proxy_url}https://ghproxy.com/https://github.com/jeffreytse/zsh-vi-mode" ~/.oh-my-zsh/custom/plugins/zsh-vi-mode
# fi

if [[ ! -d ~/.oh-my-zsh/custom/plugins/vi-mode ]]; then
     git clone --depth=1 "${glabal_github_proxy_url}https://github.com/Nyquase/vi-mode" ~/.oh-my-zsh/custom/plugins/vi-mode
fi

if [[ ! -d ~/.oh-my-zsh/custom/plugins/fzf-tab ]]; then
     git clone --depth=1 "${glabal_github_proxy_url}https://github.com/Aloxaf/fzf-tab" ~/.oh-my-zsh/custom/plugins/fzf-tab
fi

# 自动补全
if [[ ! -f ~/.oh-my-zsh/custom/plugins/incr/incr.plugin.zsh ]]; then
    if [[ ! -d ~/.oh-my-zsh/custom/plugins/incr ]]; then
      mkdir ~/.oh-my-zsh/custom/plugins/incr
    fi
    if [[ ! -x "$(which wget)" ]]; then
	echo "[INFO] wget https://mimosa-pudica.net/src/incr-0.2.zsh -O ~/.oh-my-zsh/custom/plugins/incr/incr.plugin.zsh"
    	wget https://mimosa-pudica.net/src/incr-0.2.zsh -O ~/.oh-my-zsh/custom/plugins/incr/incr.plugin.zsh
    else
	echo "[INFO] curl -R -O https://mimosa-pudica.net/src/incr-0.2.zsh ; mv ./incr-0.2.zsh ~/.oh-my-zsh/custom/plugins/incr/incr.plugin.zsh "
	curl -R -O https://mimosa-pudica.net/src/incr-0.2.zsh
        mv ./incr-0.2.zsh ~/.oh-my-zsh/custom/plugins/incr/incr.plugin.zsh
    fi
else
  source ~/.oh-my-zsh/custom/plugins/incr/incr*.zsh
fi

if [[ ! -d ~/.local ]]; then
  mkdir ~/.local
fi

# 判断lua是否存在
if [[ ! -x "$(which lua)" ]]; then
  # 下载
  curl -R -O https://www.lua.org/ftp/lua-5.4.6.tar.gz
  mv lua-5.4.6.tar.gz ~/Downloads/
  cd ~/Downloads
  # 解压
  tar zxf lua-5.4.6.tar.gz
  # 进入目录 
  cd lua-5.4.6
  # 执行编译测试 编译源码，等待它编译完成
  make macosx test
  # 执行安装
  sudo make install
fi


# 解压到指定位置
extract2path(){
  echo "[Debug] === extract2path()  ==="
  target_file_path=$1
  echo "[Debug] target_file_path = $target_file_path"
  extract_file_path=$2
  echo "[Debug] extract_file_path = $extract_file_path"
  move_file_path=$3
  echo "[Debug] move_file_path = $move_file_path"
  download_file_save_path=$4
  echo "[Debug] download_file_save_path = $download_file_save_path"
  # 判断参数是否为空
  if [ ! -n "$4" ]; then
    download_file_save_path="$HOME/Downloads"
  else
    echo "[INFO] 参数不为空!"
    download_file_save_path=$4
  fi
  echo "[Debug] download_file_save_path = $download_file_save_path"

  # 判断是什么文件，使用不同解压命令解压
  ext_name=`echo $target_file_path | awk -F'/' '{print $NF}' | awk -F'.' '{print $NF}' `
  echo "[Debug] ext_name = $ext_name"
  # 解压
  case $ext_name in
    'zip')   
        echo "[Debug] $target_file_path 是 *.zip"
        # unzip -d ~/.local/bin ./ffmpeg-113507-gf6b7b473d4.zip
        # unzip -d "$HOME/Downloads"  "$target_file_path"
        unzip -d "$download_file_save_path"  "$target_file_path"

        # unzip -v  -d "$download_file_save_path"  "$target_file_path"  | grep 'Stored' |awk '{print $8}' |sed 's!/!!' # 获取解压后的列表
        # [shell获取unzip解压后的文件夹名_unzip 解压文件名获取-CSDN博客](https://blog.csdn.net/weixin_43935187/article/details/115178270)
    ;;
    '.tar.gz' | 'gz'  ) 
        echo "[Debug] $target_file_path 是*.tar.gz"
        # 解压
        # tar zxf $target_file_path -C "$HOME/Downloads"
        tar zxf $target_file_path -C "$download_file_save_path"
    ;;
    *) 
      echo "[Debug] $target_file_path 是未知格式不知道如何解压"
    ;;
  esac
  # 解压后 移动到指定位置
  # cd "$HOME/Downloads"
  cd "$download_file_save_path"
  # pwd
  # ls
  cp $move_file_path $extract_file_path
  cd -
}

# 下载
file_downloader(){
  echo "[Debug] === file_downloader()  ==="
  file_download_url=$1
  echo "[Debug] file_download_url = $file_download_url"
  # 判断参数是否为空
  if [ ! -n "$2" ]; then
    echo "[Debug] 参数为空!"
    download_file_save_path="$HOME/Downloads"
    file_name=`echo $file_download_url | awk -F'/' '{print $NF}'`
    # file_name=`echo $file_download_url | rev | cut -d '/' -f 1 | rev`
    echo "[Debug] file_name = $file_name"
    save_file_path="$HOME/Downloads/$file_name"
    save_file_path="$2/$file_name"
  else
    echo "[Debug] 参数不为空!"
    save_file_path=$2
  fi
  echo "[Debug] save_file_path = $save_file_path"

  # 判断是否文件存在
  if [[ ! -f "$save_file_path" ]]; then
    echo "[Debug] 文件 $save_file_path 不存在！现在开始下载..."
    if [[  -x "$(which axel)" ]]; then
      echo "[Debug] 使用axel下载 $file_download_url"
      axel --output "$save_file_path" "$file_download_url"
    elif [[  -x "$(which wget)" ]]; then 
      echo "[Debug] 使用wget下载 $file_download_url"
      # wget https://evermeet.cx/ffmpeg/ffmpeg-113507-gf6b7b473d4.zip 
      # wget -c "$file_download_url"
      wget -c -O  "$save_file_path" "$file_download_url"
      # wget -b -c "$file_download_url" # 后台下载+断点续传
    else
      echo "[Debug] 使用curl下载 $file_download_url"
      cd $download_file_save_path
      curl -C -# -R -O -I "$file_download_url" 
      curl -R -O  "$file_download_url"  -o "$save_file_path" # 显示下载进度、断点下载
      # -O 将文件下载到当前目录下
      # -o 将文件 下载到 download 目录下，并重命名为 test.txt
      # -# 显示下载进度
      # -C 断点续传
      # [Linux 中三个下载工具-wget curl axel - 知乎](https://zhuanlan.zhihu.com/p/451426230)
    fi
  else 
    echo "[INFO] 文件 $save_file_path 存在！"
  fi
}

# 
binary_downloader_install(){
    # echo "[Debug] === binary_downloader_install()  ==="

    software_name=$1
    # echo "[Debug] software_name = $software_name"
    target_file_download_url=$2
    # echo "[Debug] target_file_download_url = $target_file_download_url"
    move_file_path=$3
    # echo "[Debug] move_file_path = $move_file_path"
    download_file_save_path=$4
    # echo "[Debug] download_file_save_path = $download_file_save_path"
    binary_export_path=$5
    # echo "[Debug] binary_export_path = $binary_export_path"

    if [[ ! -x $(which "$software_name") ]]; then
      # echo "[Debug] which  = $software_name"
      file_path="$binary_export_path/$software_name"
      if [[ ! -f "$file_path" ]]; then
          if [[ ! -d $binary_export_path ]]; then
            mkdir $binary_export_path
          else
            # echo "[INFO] $binary_export_path 已经存在."
          fi
          file_name=`echo $target_file_download_url | awk -F'/' '{print $NF}'`
          # file_name=`echo $file_download_url | rev | cut -d '/' -f 1 | rev`
          file_save_path="$download_file_save_path/$file_name"
          # echo "[Debug] file_save_path  = $file_save_path"
          file_downloader $target_file_download_url $file_save_path

          # extract_path="$HOME/.local/bin"
          extract_path=$binary_export_path
          # echo "[Debug] extract_path  = $extract_path"
          # 解压到指定位置并赋予执行权限
          # extract2path $file_save_path $extract_path "./fzf"
          extract2path $file_save_path $extract_path $move_file_path
          chmod +x "$extract_path/$software_name" # 赋予执行权限
          # rm -f "$download_file_save_path/$software_name" $file_save_path # 删除过程文件
          rm -f "$download_file_save_path/$software_name" "$download_file_save_path/$move_file_path" # 删除过程文件
      # else
      #   echo "[INFO] $file_path 已经存在."
      fi
    # else
    #   echo "[INFO] $software_name 已经存在."
    fi
}

# 二进制
binary_downloader_install_main(){
    # echo "[Debug] === binary_downloader_install_main()  ==="

    software_name=$1
    # echo "[Debug] software_name = $software_name"
    target_file_download_url=$2
    # echo "[Debug] target_file_download_url = $target_file_download_url"
    # 判断参数是否为空
    if [ ! -n "$3" ]; then
      # echo "[Debug] 参数为空!"
      move_file_path="./$software_name"
    else
      # echo "[Debug] 参数不为空!"
      move_file_path=$3
    fi
    # echo "[Debug] move_file_path = $move_file_path"

    # github_proxy="https://gh.api.99988866.xyz/"
    # github_proxy="https://github.moeyy.xyz/"
    github_proxy="${glabal_github_proxy_url}"
    download_file_save_path="$HOME/Downloads"
    binary_export_path="$HOME/.local/bin"
    # binary_export_path="/usr/local/bin"
    # binary_export_path="$HOME/Documents/bin"

    # 如果是github 加代理
    domain_name=`echo $target_file_download_url | awk -F'/' '{print $3}'`
    # echo "[Debug] domain_name=$domain_name"
    if [ "github.com" = "$domain_name" ] ; then
      # echo "[Debug] $target_file_download_url 下载链接是 github.com"
      target_file_download_url="$github_proxy$target_file_download_url"
    # else
    #   echo "[Debug] $target_file_download_url 下载链接不是 github.com 是 $domain_name"
    fi
    # echo "[Debug] === $target_file_download_url"

    # 
    binary_downloader_install $software_name $target_file_download_url $move_file_path $download_file_save_path $binary_export_path
}


# 判断ffmpeg是否存在，不存在则自动下载并解压
binary_downloader_install_main "ffmpeg"      "https://evermeet.cx/ffmpeg/ffmpeg-115189-g0664cbd732.zip"  './ffmpeg'  # ffmpeg   的 macOS 的二进制可执行文件
# binary_downloader_install_main "ffprobe"     "https://evermeet.cx/ffmpeg/ffprobe-115189-g0664cbd732.zip" './ffprobe'  # ffprobe  的 macOS 的二进制可执行文件
# binary_downloader_install_main "ffplay"      "https://evermeet.cx/ffmpeg/ffplay-113169-ge1c1dc8347.zip"  './ffplay'  # ffplay   的 macOS 的二进制可执行文件
# binary_downloader_install_main "ffserver"    "https://evermeet.cx/ffmpeg/ffserver-89723-g2ca65fc7b7.zip" './ffserver'  # ffserver 的 macOS 的二进制可执行文件

# B站视频下载命令行工具
## 判断BBDown是否存在，不存在则自动下载并解压
binary_downloader_install_main "BBDown"      "https://github.com/nilaoda/BBDown/releases/download/1.6.2/BBDown_1.6.2_20240512_osx-x64.zip" './BBDown' # B站视频下载

if [[ ! -f ~/.local/bin/BBDown.config ]]; then
    if [[ ! -d ~/.local/bin ]]; then
      mkdir ~/.local/bin
    fi
    echo "--work-dir $HOME/Downloads" --skip-ai False > "$HOME/.local/bin/BBDown.config" 
fi


# 跨平台的DASH/HLS/MSS下载工具
# https://github.com/nilaoda/N_m3u8DL-RE/releases/download/v0.2.0-beta/N_m3u8DL-RE_Beta_osx-x64_20230628.tar.gz
binary_downloader_install_main "N_m3u8DL-RE" "https://github.com/nilaoda/N_m3u8DL-RE/releases/download/v0.2.0-beta/N_m3u8DL-RE_Beta_osx-x64_20230628.tar.gz" './N_m3u8DL-RE_Beta_osx-x64/N_m3u8DL-RE' # m3u8 视频链接下载ts合并 的 macOS 的二进制可执行文件


# Fzf https://github.com/junegunn/fzf
# 判断是否存在，不存在则自动下载并解压
# [非交互从github中下载最新版安装包-CSDN博客](https://blog.csdn.net/qq_41961459/article/details/109404304)
# [下载github仓库最新的releases_如何从 github 下载最新临时版本-CSDN博客](https://blog.csdn.net/qq_39846820/article/details/115056151)
# github官方的api获取最近的 releases信息 https://api.github.com/repos/[仓库路径名:仓库名/项目名]/releases/latest
# 例子：                               https://api.github.com/repos/junegunn/fzf/releases/latest
binary_downloader_install_main "fzf"         "https://github.com/junegunn/fzf/releases/download/0.46.1/fzf-0.46.1-darwin_amd64.zip" './fzf'
#if [[ -f "$HOME/.local/bin/fzf ]]; then
#    export FZF_BASE="$HOME/.local/bin/fzf
#fi

# 终端代码片段管理器：nap
binary_downloader_install_main "nap"         "https://github.com/maaslalani/nap/releases/download/v0.1.1/nap_0.1.1_darwin_amd64.tar.gz" "./nap"

# git客户端TUI管理器：lazygit
binary_downloader_install_main "lazygit"      "https://github.com/jesseduffield/lazygit/releases/download/v0.42.0/lazygit_0.42.0_Darwin_x86_64.tar.gz" "./lazygit"

# superfile 命令行文件管理
# binary_downloader_install_main "superfile"   https://github.com/yorukot/superfile/releases/download/v1.1.6/superfile-darwin-v1.1.6-amd64.tar.gz

plugins=(
  git
  vi-mode
  zsh-autosuggestions
  zsh-history-substring-search
  zsh-syntax-highlighting
  fzf
  fzf-tab
  z
)

#zsh-syntax-highlighting
source $ZSH/oh-my-zsh.sh

# 插件配置

## fzf配置
## - fzf 预览图片
### - 设置高度 边框

export FZF_DEFAULT_OPTS="--layout=reverse --inline-info \
                        --height=100% \
                        --header='[tab:复制][Shift-tab:多选][ctrl-w:预览窗位置]' \
                        --header-first \
                        --preview-window="hidden:wrap" \
                        --bind='ctrl-w:change-preview-window(down|right|up|)' \
                        --bind='tab:execute( echo {}  | pbcopy )+abort' \
                        --cycle \
                        --preview 'bash $HOME/.config/scripts/preview/file_preview.sh {}'"


if [[ -x "$(which fd)" ]]; then
    ### - 设置使用fd 来查找文件, 并排除了一些项目, 让模糊查找的时候不包括这些项目.
    # export FZF_DEFAULT_COMMAND="fd --exclude={.git,.idea,.vscode,.sass-cache,node_modules,build,dist,vendor} --type f"
    export FZF_DEFAULT_COMMAND="fd --hidden --strip-cwd-prefix --exclude .git"
    export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
    export FZF_ALT_C_COMMAND="fd --type=d --hidden --strip-cwd-prefix --exclude .git"
    _fzf_compgen_path(){
      fd --hidden --exclude .git . "$1"
    }
    _fzf_compgen_dir(){
      fd --type=d --hidden --exclude .git . "$1"
    }
fi

export FZF_PREVIEW_COMMAND='bash $HOME/.config/scripts/preview/file_preview.sh {}'


_fzf_comprun() {
  local command=$1
  shift
  if [ -x  "$(which eza)" ]; then
    #statements
    case "$command" in
      cd)           fzf  --preview-window="right"  --preview 'eza --tree --color=always {} | head -200' "$@" ;;
      export|unset) fzf  --preview "eza 'echo \$' {}" "$@" ;;
      ssh)          fzf  --preview "dig' {}" "$@" ;;
      *)            fzf "$@" ;;
    esac
  elif [ -x  "$(which tree)" ]; then
    case "$command" in
      cd)           fzf "$@" --preview-window="right"  --preview 'tree -C {} | head -200' ;;
      export|unset) fzf  --preview "eza 'echo \$' {}" "$@" ;;
      ssh)          fzf  --preview "dig' {}" "$@" ;;
      *)            fzf "$@" ;;
    esac
  else
    case "$command" in
      cd)           fzf "$@" --preview-window="right"  --preview 'ls {} | head -200' ;;
      ssh)          fzf  --preview "dig' {}" "$@" ;;
      *)            fzf "$@" ;;
    esac
  fi

}

# FZF快捷键 
# CTRL-R : 从历史记录中将所选命令粘贴到命令行上
# CTRL-T: 将选定的文件或者目录粘贴到命令行上
# ALT-C cd进入所选目录

# 可通过设置FZF_CTRL_T_COMMAND覆盖默认命令；
# 可通过设置FZF_CTRL_T_OPTS设置其他选项；
# 可通过设置FZF_ALT_C_COMMAND以覆盖默认命令；
# 可通过设置FZF_ALT_C_OPTS设置其他选项；


## z.lua 配置
ZLUA="$HOME/.config/z.lua"
if [ ! -d "$ZLUA" ]; then
  echo "Installing ..."
  #URL="https://github.com/skywind3000/z.lua"
  URL="https://gitclone.com/github.com/skywind3000/z.lua"
  if [ -x "$(which git)" ]; then
    echo "git 克隆 URL 到 ($ZLUA)"
    git clone --depth 1 "$URL" "$ZLUA"
  else
    echo "ERROR: please install git  before installation !!"
    exit
  fi
  if [ ! $? -eq 0 ]; then
    echo ""
    echo "ERROR: downloading  ($URL) failed !!"
    exit
  fi;
fi
### ZSH 初始化
eval "$(lua ~/.config/z.lua/z.lua --init zsh enhanced once echo)" 

# - 设置 `$_ZL_CMD` 来改变命令名称 (默认为 z)。
# - 设置 `$_ZL_DATA` 来改变数据文件 (default ~/.zlua)。
# - 设置 `$_ZL_NO_PROMPT_COMMAND` 为 1 来跳过钩子函数初始化（方便自己处理）。
# - 设置 `$_ZL_EXCLUDE_DIRS` 逗号分隔的路径列表，列表内的路径不会被收集。
# - 设置 `$_ZL_ADD_ONCE` 为 '1' 时，仅在当前路径 `$PWD` 改变时才更新数据库。
# - 设置 `$_ZL_MAXAGE` 来确定一个数据老化的阀值 (默认为 5000)。
# - 设置 `$_ZL_CD` 用来指定你想用的 cd 命令，比如有人用 cd_func 。
# - 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。
# - 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。
# - 设置 `$_ZL_HYPHEN` 为 1 可以允许关键字中包含横线 （横线默认是 lua 正则关键字，要转写成 `%-`）。

alias zh='z -I -t .'   # 回到历史路径，用 fzf 进行历史路径操作
alias zi='z -i'        # 使用交互式选择模式
alias zf='z -I'        # 使用 fzf 对多个结果进行选择
alias zb='z -b'        # 快速回到父目录

## autojump 配置
# [ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh

#fast-syntax-highlighting
# 自定义命令
# 使用cd fd fzf 查找与切换vim文件
vimf(){
    # 加 --multi 可按tab 多选
    # 加 --cycle 选项循环
    vim $(fzf --cycle --multi --header=请选择（tab多选） --preview 'cat -n {}')
}

nvimf(){
    # 加 --multi 可按tab 多选
    # 加 --cycle 选项循环
    # nvim $(fzf --preview 'cat -n {}')
    nvim $(fzf --cycle --multi --header=请选择（tab多选）  --preview 'cat -n {}')
}

# 使用cd fd fzf 查找与切换目录
cdf(){
   # cd $(fd -p '/' -t d | fzf )
   # cd $(fd -p ’/‘ -t d | fzf --preview 'ls -alh {}')
   cd $(fd  -t  d | fzf  --cycle --header=请选择 --preview 'ls -ahl {}' )
   # 加 --cycle 选项循环
}


# 使用 cd find fzf 查找与切换目录
cdff() {
  local dir
  dir=$(find ${1:-.} -path '*/\.*' -prune \
                  -o -type d -print 2> /dev/null | fzf +m) &&
  cd "$dir"
}

# 会自动出现当前目录的 fzf，选择文件之后回车即可用默认 $EDITOR 打开文件
fe() {
  local files
  IFS=$'\n' files=($(fzf-tmux --query="$1" --multi --select-1 --exit-0))
  [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
}

# 使用  fzf 查找与切换tmux
# tm - create new tmux session, or switch to existing one. Works from within tmux too. (@bag-man)
# `tm` will allow you to select your tmux session via fzf.
# `tm irc` will attach to the irc session (if it exists), else it will create it.
tm() {
  [[ -n "$TMUX" ]] && change="switch-client" || change="attach-session"
  if [ $1 ]; then
    tmux $change -t "$1" 2>/dev/null || (tmux new-session -d -s $1 && tmux $change -t "$1"); return
  fi
  session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --exit-0) &&  tmux $change -t "$session" || echo "No sessions found."
}

# fs [FUZZY PATTERN] - Select selected tmux session
#   - Bypass fuzzy finder if there's only one match (--select-1)
#   - Exit if there's no match (--exit-0)
fs() {
  local session
  session=$(tmux list-sessions -F "#{session_name}" | \
    fzf --query="$1" --select-1 --exit-0) &&
  tmux switch-client -t "$session"
}

# 快速创建tmux窗口或切换到存在的tmux窗口
# ftmux(){

# }
alias ftmux=~/.config/scripts/fzf-switch-or-create-tmux.sh
alias ft=~/.config/scripts/fzf-switch-or-create-tmux.sh
# alias ftmux=~/.config/scripts/tmux-switch-session.sh

# fkill - kill process
fkill() {
  local pid
  pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')

  if [ "x$pid" != "x" ]
  then
    echo $pid | xargs kill -${1:-9}
  fi
}

# 切换git分支
alias fgco='git checkout ${$(git branch --remote | fzf)#"origin/"}'

# merge指定分支内容
alias fgm='git merge ${$(git branch --remote | fzf)#"origin/"}'

# fzf 、 git log
fgl(){
    # git log --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit
    # git log --oneline | fzf | grep -o -E "^[0-9a-z]+" | xargs -I {} git show {}
    git log --no-merges --graph --date=format:'%Y-%m-%d %H:%M:%S' \
            --pretty=format:'%h - %d% %s (%cd) <%an>' \
            --abbrev-commit \
            | fzf --cycle | awk -F - '{print $1}'| grep -o -E "[0-9a-z]+"  | xargs -I {} git show {}
    # 加 --cycle 选项循环
}
alias gl="git log --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit"

# fzf 、 git checkout 、git log
fglc(){

    # git log --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit
    # git log --oneline | fzf | grep -o -E "^[0-9a-z]+" | xargs -I {} git checkout {}
    git log --no-merges --graph --date=format:'%Y-%m-%d %H:%M:%S' \
            --pretty=format:'%h - %d% %s (%cd) <%an>' \
            --abbrev-commit \
            | fzf --cycle  | awk -F - '{print $1}'| grep -o -E "[0-9a-z]+"  | xargs -I {} git checkout {}
    # 加 --cycle 选项循环
}

# fzf 、git status -s 、git add 
fga(){
  # 加 --cycle 选项循环
  # 加 --multi 可按tab 多选
  # git status -s | fzf --multi --preview 'bat  $( echo {} | awk -F " " '{print $2}') ' | awk -F ' ' '{print $2}'  | xargs -I {} git add {}
  git status -s | fzf  --multi --header=请选择（tab可多选） --preview 'git diff --cached $(echo {} | tr -s " " | cut -d " " -f 2)' | awk -F ' ' '{print $2}'  | xargs -I {} git add {}
}

# 设置git命令通用别名
alias gl='git pull'
alias gu='git push'
alias gs='git status -s'


# 使用timg fzf exiftool 查看图片
fimg(){
    # cd $(fd -p '/' -t d | fzf )
    # cd $(fd -p ’/‘ -t d | fzf --preview 'ls -alh {}')
    # exiftool $(fd | fzf --preview='timg -E --frames=1 --loops=1 -g $(( $COLUMNS / 2 - 4 ))x$(( $FZF_PREVIEW_LINES * 2 )) {}' )
    fd | fzf --preview='timg -E --frames=1 --loops=1 -g $(( $COLUMNS / 2 - 4 ))x$(( $FZF_PREVIEW_LINES * 2 )) {}'
    # exiftool photo.jpg #查看所有信息
    # exiftool -a -u -g1 photo.jpg #查看所有元信息，包括重复和未知标签，并按小组排列
    # exiftool -s -ImageSize -ExposureTime photo.jpg #查看图片尺寸
    # exiftool -common dir  #查看dir目录文件信息（不仅仅是图片）
    # exiftool -l  c.jpg d.jpg  #从两个图像文件打印所有信息。
    # exiftool -l -canon c.jpg d.jpg  #从两个图像文件打印标准的佳能信息。
}

# 使用timg fzf exiftool 查看图片
limg(){
    # 5x5 列网格显示 将短文件名和图像大小显示为标题
    timg --grid=5x5  --title=" %b (%wx%h) " --center  *  
}

# # fzf greenclip
# grf(){
#      # greenclip print | sed '/^$/d' | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'
#      greenclip print | sed '/^$/d' | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'; sleep 0.5; xdotool type $(xclip -o -selection clipboard)
# }

# # dmenu greenclip
# grd(){
#     # greenclip print | sed '/^$/d' | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}'
#     greenclip print | sed '/^$/d' | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}';sleep 0.5; xdotool type $(xclip -o -selection clipboard)
# }

# #  greenclip clear
# grc(){
#     pkill greenclip && greenclip clear && greenclip daemon &
# }

## 终端命令行查英语单词
v2(){
  declare q="$*";
  #curl --user-agent curl "https://v2en.co/${q// /%20}";
  curl --user-agent curl "https://d.supjohn.com/${q// /%20}";

}
## v2-sh 可以直接进入交互模式，不用重复输入 v2 前缀
v2-sh(){
  while echo -n "v2en>";
  read -r input;
  [[ -n "$input" ]]
  do v2 "$input";
  done
}


# ranger 配置
## 会自动切换到最后一次浏览的目录.
# rangerhistory(){
ranger_cd() {
    temp_file="$(mktemp -t "ranger_cd.XXXXXXXXXX")"
    # ranger --choosedir="$temp_file" -- "${@:-$PWD}"        # 退出ranger后不会切换到最后停留的目录地址
    source ranger --choosedir="$temp_file" -- "${@:-$PWD}"   # 退出ranger后会切换到最后停留的目录地址
    if chosen_dir="$(cat -- "$temp_file")" && [ -n "$chosen_dir" ] && [ "$chosen_dir" != "$PWD" ]; then
        cd -- "$chosen_dir"
    fi
    rm -f -- "$temp_file"
}

# 使用rg和fzf搭配递归查找当前文件夹下内容
rg_fzf_find()
{
    # rg --column --smart-case  -- '' | fzf
    # rg --column --smart-case  -- '' | fzf --preview 'cat -n $( echo {} | cut -d : -f 1)'
    result=`rg --column --smart-case  -- '' | fzf --preview 'bat  $( echo {} | cut -d : -f 1)   --color=always  --wrap=auto  --style=numbers  --highlight-line=$(echo {} | cut -d : -f 2):$(echo {} | cut -d : -f 2)  --line-range=$(( $(( $(echo {} | cut -d : -f 2)-18 ))>18?$(( $(echo {} | cut -d : -f 2)-18 )):1 )):$(( $(echo {} | cut -d : -f 2)+18 ))  '`
    # echo "[Debug]=======${result}"
    if [ -f "$(echo ${result} | cut -d : -f 1)" ]; then
        vim  -o $(echo ${result} | cut -d : -f 1) + $(echo ${result} | cut -d : -f 2) 
    else
        echo "取消选择"
    fi
}

# rg 参数说明
# -M --max-depth 限制文件夹递归搜索深度。rg --max-depth 0 dir/则不执行任何搜索；rg --max-depth 1 dir/只在dir/当前目录中进行搜索。

# 使用ack和fzf搭配递归查找当前文件夹下内容
ack_fzf_find()
{
    # ack foo --js -A 2 -B 2 # 在当前目录下，查找js文件中包含foo文本，并打印与其相关的上下2行
    result=`ack -- '' | fzf --preview 'bat  $( echo {} | cut -d : -f 1)   --color=always  --wrap=auto  --style=numbers  --highlight-line=$(echo {} | cut -d : -f 2):$(echo {} | cut -d : -f 2)  --line-range=$(( $(( $(echo {} | cut -d : -f 2)-18 ))>18?$(( $(echo {} | cut -d : -f 2)-18 )):1 )):$(( $(echo {} | cut -d : -f 2)+18 ))  '`
    # echo "[Debug]=======${result}"
    # vim -o $(echo ${result} | cut -d : -f 1) +$(echo ${result} | cut -d : -f 2)
    if [ -f "$(echo ${result} | cut -d : -f 1)" ]; then
        vim -o $(echo ${result} | cut -d : -f 1) + $(echo ${result} | cut -d : -f 2) 
    else
        echo "取消选择"
    fi
}

alias r='ranger'
alias rc='source ranger'  # 退出ranger后会切换到最后停留的目录地址
alias rh='ranger_cd'

# 设置命令通用别名
alias cls='clear'
# alias la='ls -a'
if [ -x  "$(which eza)" ]; then
  # alias ll="eza --color=always --long --git --no-filesize --icons=always --no-user --no-permissions --no-time"
  alias ll="eza --color=always --long --git --no-filesize --icons=always"
else
  alias ll='ls -l'
fi
alias vi='vim'
alias javac="javac -J-Dfile.encoding=utf8"
alias grep="grep --color=auto"

## 针对文件类型设置对应的打开程序
# alias -s html=mate               # 在命令行直接输入后缀为 html 的文件名，会在 TextMate 中打开，以下类似
# alias -s rb=mate                 # 在命令行直接输入 ruby 文件，会在 TextMate 中打开
alias -s py=vim                   # 在命令行直接输入 python 文件，会用 vim 中打开
alias -s js=vim                   # 在命令行直接输入 js 文件，会用 vim 中打开
alias -s c=vim                    # 在命令行直接输入 c 文件，会用 vim 中打开
alias -s java=vim                # 在命令行直接输入 java 文件，会用 vim 中打开
alias -s txt=vim                 # 在命令行直接输入 txt 文件，会用 vim 中打开

alias -s gz='tar -xzvf'          # 在命令行直接输入 文件名，会自动解压后缀为 gz 的压缩包
alias -s tgz='tar -xzvf'         # 在命令行直接输入 文件名，会自动解压后缀为 tgz 的压缩包
alias -s zip='unzip'             # 在命令行直接输入 文件名，会自动解压后缀为 zip 的压缩包
alias -s bz2='tar -xjvf'         # 在命令行直接输入 文件名，会自动解压后缀为 bz2 的压缩包

# 按 Ctrl-P 与 Ctrl-N 在历史命令记录搜索切换。
# bindkey '^P' history-search-backward
# bindkey '^N' history-search-forward
bindkey '^P' history-substring-search-up
bindkey '^N' history-substring-search-down

# zsh的vi-mode配置
bindkey -v
# zsh下模式切换模式光标变化（插入模式光标变成 细竖条  命令模式变为粗竖条 ）
function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] || [[ $1 = 'block' ]]; then
    echo -ne '\e[1 q'
  elif [[ ${KEYMAP} == main ]] || [[ ${KEYMAP} == viins ]] || [[ ${KEYMAP} = '' ]] || [[ $1 = 'beam' ]]; then
    echo -ne '\e[5 q'
  fi
}
zle -N zle-keymap-select

# Use beam shape cursor on startup. 开始时光标是细竖条
echo -ne '\e[5 q'

# Use beam shape cursor for each new prompt.
preexec() {
  echo -ne '\e[5 q'
}

_fix_cursor() {
  echo -ne '\e[5 q'
}
precmd_functions+=(_fix_cursor)

# vi-mode下历史命令搜索切换
bindkey -M vicmd 'k' history-substring-search-up
bindkey -M vicmd 'j' history-substring-search-down

# 热键绑定
# 查看当前绑定(使用 bindkey 命令即可)
# "^@" set-mark-command
# "^A" beginning-of-line
# "^B" backward-char
# "^D" delete-char-or-list
# "^E" end-of-line
# "^F" forward-char
# "^G" send-break
# "^H" backward-delete-char
# "^I" expand-or-complete
# "^J" accept-line
# "^K" kill-line
# "^L" clear-screen
# "^M" accept-line
# "^N" down-line-or-history
# "^O" accept-line-and-down-history
# "^P" up-line-or-history
# "^Q" push-line
# "^R" history-incremental-search-backward
# "^S" history-incremental-search-forward
# "^T" transpose-chars
# "^U" kill-whole-line
# "^V" quoted-insert
# "^W" backward-kill-word
# "^X^B" vi-match-bracket
# "^X^F" vi-find-next-char
# "^X^J" vi-join
# "^X^K" kill-buffer
# "^X^N" infer-next-history
# "^X^O" overwrite-mode
# "^X^U" undo
# "^X^V" vi-cmd-mode
# "^X^X" exchange-point-and-mark
# "^X*" expand-word
# "^X=" what-cursor-position
# "^XG" list-expand
# "^Xg" list-expand
# "^Xr" history-incremental-search-backward
# "^Xs" history-incremental-search-forward
# "^Xu" undo
# "^Y" yank
# "^[^D" list-choices
# "^[^G" send-break
# "^[^H" backward-kill-word
# "^[^I" self-insert-unmeta
# "^[^J" self-insert-unmeta
# "^[^L" clear-screen
# "^[^M" self-insert-unmeta
# "^[^_" copy-prev-word
# "^[ " expand-history
# "^[!" expand-history
# "^[\"" quote-region
# "^[\$" spell-word
# "^['" quote-line
# "^[-" neg-argument
# "^[." insert-last-word
# "^[0" digit-argument
# "^[1" digit-argument
# "^[2" digit-argument
# "^[3" digit-argument
# "^[4" digit-argument
# "^[5" digit-argument
# "^[6" digit-argument
# "^[7" digit-argument
# "^[8" digit-argument
# "^[9" digit-argument
# "^[<" beginning-of-buffer-or-history
# "^[>" end-of-buffer-or-history
# "^[?" which-command
# "^[A" accept-and-hold
# "^[B" backward-word
# "^[C" capitalize-word
# "^[D" kill-word
# "^[F" forward-word
# "^[G" get-line
# "^[H" run-help
# "^[L" down-case-word
# "^[N" history-search-forward
# "^[OA" up-line-or-search
# "^[OB" down-line-or-search
# "^[OC" forward-char
# "^[OD" backward-char
# "^[OF" end-of-line
# "^[OH" beginning-of-line
# "^[P" history-search-backward
# "^[Q" push-line
# "^[S" spell-word
# "^[T" transpose-words
# "^[U" up-case-word
# "^[W" copy-region-as-kill
# "^[[200~" bracketed-paste
# "^[[3~" delete-char
# "^[[A" up-line-or-history
# "^[[B" down-line-or-history
# "^[[C" forward-char
# "^[[D" backward-char
# "^[_" insert-last-word
# "^[a" accept-and-hold
# "^[b" backward-word
# "^[c" capitalize-word
# "^[d" kill-word
# "^[f" forward-word
# "^[g" get-line
# "^[h" run-help
# "^[l" down-case-word
# "^[n" history-search-forward
# "^[p" history-search-backward
# "^[q" push-line
# "^[s" spell-word
# "^[t" transpose-words
# "^[u" up-case-word
# "^[w" copy-region-as-kill
# "^[x" execute-named-cmd
# "^[y" yank-pop
# "^[z" execute-last-named-cmd
# "^[|" vi-goto-column
# "^[^?" backward-kill-word
# "^_" undo
# " "-"~" self-insert
# "^?" backward-delete-char
# "\M-^@"-"\M-^?" self-insert

# 常用默认按键
# ctrl + A，移动到行首 （这里是小写好像被占 使用大写 所以是 Ctrl + Shift + a）
# ctrl + e，移动到行尾
# ctrl + f，前移一个字符
# ctrl + b，后移一个字符
# ctrl + w，删除光标前面的单词
# ctrl + d，删除光标所指的字符
# ctrl + k，删除光标至行尾的所有内容
# ctrl + u，清空当前行

# Alt键+
# 在使用 bindkey 命令时，一帮第一个参数使用对应快捷键的 CSI 序列
# bindkey '\e[1;3D' backward-word       # ALT+左键   ：向后跳一个单词
# bindkey '\e[1;3C' forward-word        # ALT+右键   ：前跳一个单词
# bindkey '\e[1;3A' beginning-of-line   # ALT+上键   ：跳到行首
# bindkey '\e[1;3B' end-of-line         # ALT+下键   ：调到行尾

# bindkey '\eh' backward-char        # ALT + h : 向左移动一个单词
# bindkey '\el' forward-char         # ALT + l ：向右移动一个单词
# bindkey '\ek' up-line-or-history   # ALT + k ：向上移动一个单词
# bindkey '\ej' down-line-or-history # ALT + j ：向下移动一个单词

bindkey -s '\eo'   'cd ..\n'          # ALT+O      ：执行 cd .. 命令
bindkey -s '\e;'   'ls -l\n'          # ALT+;      ：执行 ls -l 命令
bindkey -s '\ef'   'rg_fzf_find\n'    # ALT+f      ：执行 rg_fzf_find 命令
# bindkey -s '\ef;' 'cdf\n'             # ALT+f;     ：执行 cdf 命令


# Ctrl键+
bindkey '^b' backward-word            # Ctrl + b ：向后跳一个单词
bindkey '^f' forward-word             # Ctrl + f ：前跳一个单词
# bindkey '^a' beginning-of-line        # Ctrl + a ：跳到行首
# bindkey '^e' end-of-line              # Ctrl + e ：调到行尾

bindkey '^h' backward-char            # Ctrl + h : 向左移动一个单词
bindkey '^l' forward-char             # Ctrl + l ：向右移动一个单词
# bindkey '^k' up-line-or-history       # Ctrl + k ：向上移动一个单词
# bindkey '^j' down-line-or-history     # Ctrl + j ：向下移动一个单词
bindkey '^d' delete-char-or-list       # 删除光标所在单词或
bindkey '^k' kill-line                 # 删除光标之后的

#bindkey '^i' autosuggest-accept       # ctrl+.     ：将建议的历史填充到命令行输入 （默认使用方向右键）

bindkey -s '^g'    'git pull\n'       # Ctrl+f     ：执行 git pull 命令
# bindkey -s '^g'    'lazygit\n'        # Ctrl+g     ：执行 lazygit 命令
# bindkey -s '^f'    'cdf\n'            # Ctrl+f     ：执行 cdf 命令
bindkey -s '^[f'   'rg_fzf_find\n'    # Ctrl+z+f   ：执行 rg_fzf_find 命令
bindkey -s '^af'   'ack_fzf_find\n'   # Ctrl+s+f   ：执行 ack_fzf_find 命令


 
# lf () {
#     LF_TEMPDIR="$(mktemp -d -t lf-tempdir-XXXXXX)"
#     LF_TEMPDIR="$LF_TEMPDIR" lf-run -last-dir-path="$LF_TEMPDIR/lastdir" "$@"
#     if [ "$(cat "$LF_TEMPDIR/cdtolastdir" 2>/dev/null)" -eq 1 ]; then
#         cd "$(cat "$LF_TEMPDIR/lastdir")"
#     fi
#     rm -r "$LF_TEMPDIR"
#     unset LF_TEMPDIR
# }
#alias lf='lf-ueberzug'        # 图片预览的LF
alias l='lfrun'        # 图片预览的LF
alias lc='lfcd'        # 图片预览的LF

[ -f ~/.config/lf/lfcd.sh ] && source ~/.config/lf/lfcd.sh
bindkey -s '^o' 'lfcd\n'  # Ctrl+o 进入lfcd的最后目录


alias fscp=~/.config/scripts/fzf-sshscp/scp.sh
alias fssh=~/.config/scripts/fzf-sshscp/ssh.sh
alias fsql=~/.config/scripts/fzf-sql/sql.sh

alias fcmd=~/.config/scripts/fzf-tools/cmd.sh

alias demo=~/.config/scripts/demo.sh

# 下载
# 格式： m3u8dl 电影名  https://xxxxx.xxx.xx/index.m3u8
m3u8dl(){
    file_name=$1
    down_url_addr=$2
    download_file_save_path="$HOME/Downloads/$file_name.mp4"
    if [ ! -f "$download_file_save_path" ]; then
      echo "[INFO] $download_file_save_path 不存在！"
      cmdStr="ps aux | grep $file_name | grep N_m3u8DL-RE | awk '{print \$2}'"
      echo "[INFO] 命令： $cmdStr"
      ps_id=`eval $cmdStr`
      # echo "[Debug] ps_id = $ps_id "
      if [ ! -n "$ps_id" ]; then
        echo "[INFO] 不是正在下载进行中..."
        if [ -x "$(which N_m3u8DL-RE)" ]; then
            # cmdStr="$HOME/.local/bin/N_m3u8DL-RE --tmp-dir=$HOME/Downloads --save-dir=$HOME/Downloads --save-name=$file_name $down_url_addr"
            cmdStr="N_m3u8DL-RE --tmp-dir=$HOME/Downloads --save-dir=$HOME/Downloads --save-name=$file_name '$down_url_addr'"
            echo "[INFO] 命令： $cmdStr"
            # 执行命令
            # N_m3u8DL-RE --tmp-dir=$HOME/Downloads --save-dir=$HOME/Downloads --save-name=$file_name $down_url_addr
            eval $cmdStr
        else
            echo "[INFO] 没有安装或配置好 N_m3u8DL-RE "
        fi
      else
        echo "[INFO] 有进程正在下载 $file_name 中 (进程ID: $ps_id ) ."
      fi
    else
        echo "[INFO] $download_file_save_path 已经存在."
    fi
}


# 格式转化
# 格式： ts2mp4  ./少年歌行06.ts
# ffmpeg -i ./少年歌行06.ts -acodec  copy -vcodec copy  -f mp4 少年歌行06.mp4
ts2mp4(){
    if [ -x "$(which ffmpeg)" ]; then
        case "$1" in
            *.ts) filepath=$1
                  filename="$(echo $filepath |  awk -F'.ts' '{print $1}')"
                  # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                  echo "[INFO] filepath $filepath"
                  echo "[INFO] filename = $filename"
                  newfilename=$filename".mp4"
                  echo "[INFO] newfilename = $newfilename"

                  # echo "[INFO] $filenext"
                  cmdStr="ffmpeg -i $filepath -acodec  copy -vcodec copy  -f mp4 $newfilename"
                  echo "[INFO] 命令：$cmdStr"
                  # 执行命令
                  # ffmpeg -i $filepath -acodec  copy -vcodec copy  -f mp4 $newfilename
                  eval $cmdStr
            ;;
            # *.md) glow -s dark "$1" ;;
            # *) bat --color=always --italic-text=always --style=numbers,changes,header --line-range :500 "$1" ;;
            *) echo "[INFO] 不是 .ts 文件";;
        esac
        echo "[INFO] Over ."
    else
        echo "[INFO] 没有安装或配置好 ffmpeg "
    fi
}

multiple-ts2mp4(){
  # 判断是否为空
  target_path=$1
  if [ ! -n "$target_path" ] ;then
      echo "you have not input a word!"
      target_path="./"
  else
      echo "[Debug] the target_path is $target_path"
  fi
  # 判断是文件还是目录
  if [ -d "$target_path" ]; then
    echo "[Debug] $target_path is a directory "
    # 遍历
    for target_per_entry in `ls $target_path`; do
        # echo "[INFO] $entry"
        target_path_full="$target_path/$target_per_entry"
        echo "[Debug] target_path_full is $target_path_full"
        if [ -f "$target_path_full" ]; then
          echo "[Debug] $target_path_full is a file"
          ts2mp4 $target_path_full
        fi
    done
  elif [ -f "$target_path" ]; then
    echo "[Debug] $target_path is a file"
    ts2mp4 $target_path
  fi

}
# [Shell脚本中判断输入变量或者参数是否为空的方法_shell脚本if判断参数不为空-CSDN博客](https://blog.csdn.net/long375577908/article/details/78498216)

gbk2utf8(){
  # 判断是否为空
  target_file_path=$1
  if [ ! -n "$target_file_path" ] ;then
      echo "[INFO] $target_file_path is empty."
  else
      echo "[Debug] the target_file_path is $target_file_path."
      if [ -f "$target_file_path" ]; then
        # echo "[Debug] $target_file_path is a file"
        new_file_name="$(echo $target_file_path |  awk -F'.txt' '{print $1}')"
        # echo "[Debug] new_file_name = $new_file_name "
        new_file_path="$new_file_name-utf8.txt"
        # echo "[Debug] new_file_path = $new_file_path "
        echo "[INFO] GBK 转 utf-8 : iconv -f gbk -t utf-8 $target_file_path > $new_file_path"
        iconv -f gbk -t utf-8 $target_file_path > $new_file_path
      fi
  fi
  
}

# 合并
# 格式： ffmpegmergets  ./诛仙01集
# 诛仙01集
# |-- 0___800000_
#     |-- 001.ts
#     |-- 002.ts
#     \-- ...
# 会生成一个tx视频文件位置txt文档然后使用 ffmpeg -f  concat -safe 0 -i ./诛仙01集-file.txt -c copy ./诛仙01集.mp4 合并
# alias ffmpeg_merge_ts=~/.config/scripts/ffmpegmergets.sh

# 使用ffmpeg 合并 m3u8下载的ts视频文件为一个mp4文件
ffmpeg_merge_ts(){
    ## 项目名称/视频名称
    prj_name=$1
    echo "[INFO] prj_name= "$prj_name
    # 获取ts文件夹路径
    search_dir=$prj_name
    # echo "[INFO] search_dir = "$search_dir
    for entry in `ls $search_dir`; do
        # echo "[INFO] $entry"
        tsfiles_dir=$search_dir"/"$entry
    done

    # 生成ffmpeg合并的ts文件列表
    # tsfiles_dir=$1
    save_file_path="./"$prj_name"-file.txt"
    # 先清空文件确保不会有已存在的内容
    :> "./"$save_file_path
    # echo "[INFO] search_dir = "$search_dir
    for entry in `ls $tsfiles_dir`; do
        # echo "[INFO] $entry"
        # 相对位置
        tsfiles_path="./"$tsfiles_dir"/"$entry
        echo "file '$tsfiles_path'" >> "./"$save_file_path
        # >    将标准输出重定向文件
        # >>   将标准输出追加到文件
    done

    # 执行合并命令
    ffmpeg -f  concat -safe 0 -i $save_file_path -c copy "./"$prj_name".mp4"
    # 使用ffmpeg进行多个视频合并过程中出现了“unsafe file name”错误，解决的办法是加个-safe 0 参数
    # 删除 txt文件
    rm -f $save_file_path
}

ffmpeg-merge-ts(){
  dir_path=$1
  echo "[INFO] dir_path="$dir_path
  # echo "a,b,c,d,e,f" | awk '{n=split($0, array, ",")} END{print n}'
  # echo "~/Downloads/战士第三季10" | awk '{n=split($0, array, "/")} END{print n}'
  # echo "~/Downloads/战士第三季10" | awk -F "/" '{print NF}'
  # [Linux如何统计一行数据根据分隔符分割后字段的数量? - 知乎](https://www.zhihu.com/question/533002625)
  # dir_path_length=`echo ${dir_path} |awk '{n=split($0, array, "/")} END{print n}'`
  dir_path_length=`echo ${dir_path} |awk -F "/" '{print NF}'`
  # 大于 -gt (greater than)
  # 小于 -lt (less than)
  # 大于或等于 -ge (greater than or equal)
  # 小于或等于 -le (less than or equal)
  # 不相等 -ne （not equal）
  if [[ ${dir_path_length} -ge 2 ]]; then
    # 分割数量大于等于2时
    ts_dir=`echo ${dir_path} | awk -F "/" '{print $NF}'`
    echo "[INFO] ts_dir="$ts_dir
    # 删除最后一个目录
    ts_p_dir=${dir_path%${ts_dir}*}${dir_path##*${ts_dir}}
    echo "[INFO] ts_p_dir="$ts_p_dir
    # [Linux shell字符串截取、替换、删除以及trim_shell trim_aabond的博客-CSDN博客](https://blog.csdn.net/qq_23091073/article/details/83066518)
    cd ${ts_p_dir}
    pwd
    # 执行合并ts视频文件
    # echo ${ts_dir}
    ffmpeg_merge_ts ${ts_dir}


    # 返回之前目录
    cd -
  else
    # echo  ${dir_path}
    # 执行合并ts视频文件
    ffmpeg_merge_ts ${dir_path}
  fi
}

# 批量合并文件夹下的m3u8的下载视频ts
multiple-ffmpeg-merge-ts(){
  dir_path=$1
  # echo "[INFO] dir_path = "$dir_path
  for entry in `ls $dir_path`; do
      # echo "[INFO] $entry"
      cd $dir_path
      # 执行合并ts视频文件
      ffmpeg_merge_ts $entry
      cd -
  done
}


fast-ffmpeg-merge(){
    dir_path=$1
    cd $dir_path
    # for entry in `ls $dir_path | grep -w -E 'mp4$|avi$' `; do
    # for entry in `ls $dir_path | grep -w -E 'mp4$' `; do
    for entry in `ls | grep -w -E 'mp4$' `; do
      # echo "[INFO] entry = $entry"
      filename="$(echo $entry |  awk -F'[0-9].mp4' '{print $1}')"
      # echo  "[INFO] filename = $filename"
      # cmdstr="ls $dir_path | grep  -E '${filename}' "
      # echo  "[INFO] cmdstr = $cmdstr"
      save_file_path="./"$filename"-file.txt"
      # 先清空文件确保不会有已存在的内容
      :> $save_file_path
      # for entry2 in `ls $dir_path | grep  -E ${filename} `; do
      for entry2 in `ls | grep  -E ${filename} | grep -w -E 'mp4$' `; do
        # echo "[INFO] entry2 = $entry2"
        # 生成ts视频列表的file.txt 文件
        # 相对位置
        files_path="./"$entry2
        echo "file '$files_path'" >> $save_file_path
        # >    将标准输出重定向文件
        # >>   将标准输出追加到文件
      done
    done

    # 读取生成的*-file.txt 合并视频
    for entry in `ls | grep -w -E 'file\.txt$' `; do
      echo "[INFO] entry = $entry"
      save_file_path=$entry
      prj_name="$(echo $entry |  awk -F'-file.txt' '{print $1}')"
      # 开始合并
      cmdStr="ffmpeg -f concat -safe 0  -i $save_file_path -c copy ./$prj_name.mp4"
      echo "[INFO] $cmdStr"
      # 执行合并命令
      ffmpeg -f  concat -safe 0 -i $save_file_path -c copy "./"$prj_name".mp4"
      # 使用ffmpeg进行多个视频合并过程中出现了“unsafe file name”错误，解决的办法是加个-safe 0 参数
      # 删除 txt文件
      rm -f $save_file_path
    done
    cd -
}

## amr2mp3
amr2mp3(){
  amr_path=$1
  echo "[INFO] amr_path="$amr_path
  if [ -x "$(which ffmpeg)" ]; then
      case "$1" in
          *.amr)  filepath=$1
                  filename="$(echo $filepath |  awk -F'.amr' '{print $1}')"
                  # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                  echo "[INFO] filepath $filepath"
                  echo "[INFO] filename = $filename"
                  newfilename=$filename".mp3"
                  echo "[INFO] newfilename = $newfilename"
                  # 执行命令
                  # cmdStr="ffmpeg -i $filepath -acodec  copy -vcodec copy  -f mp4 $filename.mp4"
                  cmdStr="ffmpeg -i $filepath  $filename.mp3"
                  echo "[INFO] $cmdStr"
                  ffmpeg -i $filepath $newfilename
          ;;
          *) echo "[INFO] 不是 .amr 文件";;
      esac
      echo "[INFO] Over ."
  else
      echo "[INFO] 没有安装或配置好 ffmpeg "
  fi
}


# 视频压缩
# 视觉无损压缩
ffmpeg-compressed(){
  # movie_file_path=$1
  # echo "[INFO] movie_file_path="$movie_file_path
  if [ -x "$(which ffmpeg)" ]; then
        case "$1" in
            *.ts|*.mp4|*.avi) filepath=$1
                  # filename="$(echo $filepath |  awk -F'.ts' '{print $1}')"
                  filename="$(echo $filepath |  awk -F'.' '{print $1}')"
                  # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                  echo "[INFO] filepath $filepath"
                  echo "[INFO] filename = $filename"
                  newfilename=$filename"-compressed.mp4"
                  echo "[INFO] newfilename = $newfilename"

                  # echo "[INFO] $filenext"
                  cmdStr="ffmpeg -i $filepath -c:v libx265 -x265-params crf=18  -f mp4 $newfilename"
                  # ffmpeg -i 输入文件名 -c:v libx265 -x265-params crf=18 output/输出文件名.mp4
                  # ffmpeg -i 输入文件名 -c:v libx265 -x265-params crf=18:preset=placebo output/输出文件名.mp4
                  echo "[INFO] $cmdStr"
                  # 执行命令
                  ffmpeg -i $filepath -acodec  copy -vcodec copy  -f mp4 $newfilename
            ;;
            # *.md) glow -s dark "$1" ;;
            # *) bat --color=always --italic-text=always --style=numbers,changes,header --line-range :500 "$1" ;;
            *) echo "[INFO] 不是 .ts 、.mp4、.avi 文件";;
        esac
        echo "[INFO] Over ."
    else
        echo "[INFO] 没有安装或配置好 ffmpeg "
    fi
}

# 视觉压缩 转码1080p
ffmpeg-compressed-1080p(){
  # ffmpeg的参数说明
  # -y：是否覆盖文件
  # -b：视频比特率,代表了视频的质量和大小，我一般高清设置6000k，超过一万，在计算机显示屏上基本肉眼无法区分，当然投影又是另外一回事了
  # -bufsize：设置视频码率缓冲区大小，和-b一致即可
  # -c:v：设置视频格式，一般视频都为libx264
  # -vf：设置视频过滤器，和后面的scale配合
  # -scale：设置视频分辨率
  if [ -x "$(which ffmpeg)" ]; then
        case "$1" in
            *.ts|*.mp4|*.avi) filepath=$1
                  # filename="$(echo $filepath |  awk -F'.ts' '{print $1}')"
                  filename="$(echo $filepath |  awk -F'.' '{print $1}')"
                  # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                  echo "[INFO] filepath $filepath"
                  echo "[INFO] filename = $filename"
                  newfilename=$filename"-compressed-1080p.mp4"
                  echo "[INFO] newfilename = $newfilename"

                  # echo "[INFO] $filenext"
                  cmdStr="ffmpeg -i $filepath -strict -2 -b 6000k -bufsize 6000k -an -c:v libx264 -vf scale=1920:1080  -f mp4 $newfilename"
                  echo "[INFO] $cmdStr"
                  # 执行命令
                  ffmpeg -i $filepath  -strict -2 -b 6000k -bufsize 6000k -an -c:v libx264 -vf scale=1920:1080  -f mp4 $newfilename
            ;;
            # *.md) glow -s dark "$1" ;;
            # *) bat --color=always --italic-text=always --style=numbers,changes,header --line-range :500 "$1" ;;
            *) echo "[INFO] 不是 .ts 、.mp4、.avi 文件";;
        esac
        echo "[INFO] Over ."
    else
        echo "[INFO] 没有安装或配置好 ffmpeg "
    fi
}

# 视觉压缩 转码720p
ffmpeg-compressed-720p(){
  # 参数说明
  # -y：是否覆盖文件
  # -b：视频比特率,代表了视频的质量和大小，我一般高清设置6000k，超过一万，在计算机显示屏上基本肉眼无法区分，当然投影又是另外一回事了
  # -bufsize：设置视频码率缓冲区大小，和-b一致即可
  # -c:v：设置视频格式，一般视频都为libx264
  # -vf：设置视频过滤器，和后面的scale配合
  # -scale：设置视频分辨率
  if [ -x "$(which ffmpeg)" ]; then
        case "$1" in
            *.ts|*.mp4|*.avi) filepath=$1
                  # filename="$(echo $filepath |  awk -F'.ts' '{print $1}')"
                  filename="$(echo $filepath |  awk -F'.' '{print $1}')"
                  # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                  echo "[INFO] filepath $filepath"
                  echo "[INFO] filename = $filename"
                  newfilename=$filename"-compressed-1080p.mp4"
                  echo "[INFO] newfilename = $newfilename"

                  # echo "[INFO] $filenext"
                  cmdStr="ffmpeg -i $filepath -strict -2 -b 3000k -bufsize 3000k -an -c:v libx264 -vf scale=1280:720  -f mp4 $newfilename"
                  echo "[INFO] $cmdStr"
                  # 执行命令
                  ffmpeg -i $filepath  -strict -2 -b 3000k -bufsize 3000k -an -c:v libx264 -vf scale=1280:720 -f mp4 $newfilename
            ;;
            # *.md) glow -s dark "$1" ;;
            # *) bat --color=always --italic-text=always --style=numbers,changes,header --line-range :500 "$1" ;;
            *) echo "[INFO] 不是 .ts 、.mp4、.avi 文件";;
        esac
        echo "[INFO] Over ."
    else
        echo "[INFO] 没有安装或配置好 ffmpeg "
    fi
}



## aria2
aria2cx(){
  if [ -x "$(which aria2c)" ]; then
    if [[ -f $HOME/.aria2/aria2.conf ]]; then
      aria2c --conf-path="${HOME}/.aria2/aria2.conf" -S "$1"
    else
      echo "[INFO] $HOME/.aria2/aria2.conf 不存在. "
    fi
  else
    echo "[INFO] 没有安装 aria2c "
  fi
}

# 压缩包密码破解
compressed-cracking(){
  # john_jumbo="/usr/local/Cellar/john-jumbo/1.9.0_1/share/john"
  compressed_file_path=$1
  echo "[INFO] compressed_file_path="$compressed_file_path
  hash_save_path="$HOME/Documents/XWorkSpaces/CompressedHash"
  # 创建一个用来存放hash文件的目录
  if [ -d $hash_save_path ]; then
    echo "[INFO] 已存在 $hash_save_path"
  else
    echo "[INFO] 不存在 $hash_save_path 。 现在创建... "
    mkdir -p "$hash_save_path"
  fi

  if [ -x "$(which hashcat)"  ]; then
      case "$1" in
          *.7z) filepath=$1
                echo "[INFO] filepath $filepath"
                # filename="$(echo $filepath |  awk -F'.7z' '{print $1}')"
                # # filenext="$(echo $filepath |  awk -F. '{print $2}')"
                # filename="$(echo $filename | awk -F"/" ' {print $NF}')"  # 其中， -F"/" 表示使用 / 作为分隔符， $NF 表示输出最后一个部分。
                filename="$(echo $filepath |  awk -F'.7z' '{print $1}' | awk -F"/" ' {print $NF}')"
                echo "[INFO] filename = $filename"
                hashstrfilename=$filename"-7z_hash.txt"
                echo "[INFO] hashstrfilename = $hashstrfilename"
                hashstrfilenameorigin=$filename"-7z_hash_origin.txt"
                echo "[INFO] hashstrfilenameorigin = $hashstrfilenameorigin"
                # # 执行命令 生成hash文件
                # cmdStr="7z2john.pl  $filepath >> $hash_save_path/$hashstrfilename"
                # cmdStr="7z2john.pl  $filepath"
                # cmdStr="7z2john.pl  $filepath |  tee -a $hash_save_path/$hashstrfilenameorigin"
                cmdStr="7z2john.pl  $filepath > $hash_save_path/$hashstrfilenameorigin"
                # cmdStr="perl $john_jumbo/7z2john.pl  $filepath |  tee -a $hash_save_path/$hashstrfilenameorigin"
                # cmdStr="$john_jumbo/7z2john.pl  $filepath "
                echo "[INFO] $cmdStr"
                # john_hash_res=`$cmdStr`
                # echo "[INFO] $john_hash_res"
                7z2john.pl  $filepath > $hash_save_path"/"$hashstrfilenameorigin
                # 读取处理
                john_hash_res=`cat $hash_save_path"/"$hashstrfilenameorigin`
                echo "[INFO] $john_hash_res"
                hash_str="$(echo $john_hash_res |  awk -F':' '{print $2}')"
                echo "[INFO] $hash_str"
                echo $hash_str > $hash_save_path"/"$hashstrfilename

                # 进行破解
                # -m 是设置 hash 类型，具体可参考 https://hashcat.net/wiki/doku.php?id=example_hashes，
                #       RAR 对应的就是 13000，相应的，
                #       ZIP 对应的就是 17210 ，
                #       7-Zip对应的hash模式为11600。
                #       MD5 是 0
                # hashcat -a 3 -m 11600  ~/Desktop/7zhash.txt --force \?d\?d\?d\?d                    # 密码为 4 位数字 进行暴力破解
                # hashcat -a 3 -m 11600  ~/Desktop/7zhash.txt --force  -1 \?l\?d    \?1\?1\?1\?1      # 密码为 4 位小写字母+数字 进行暴力破解
                # hashcat -a 3 -m 11600  ~/Desktop/7zhash.txt --force  -1 \?u\?l\?d \?1\?1\?1\?1      # 密码为 4 位大小写字母+数字 进行暴力破解
                # hashcat -a 3 -m 11600  ~/Desktop/7zhash.txt --force --increment --increment-min 4 --increment-max 8 \?a\?a\?a\?a\?a\?a\?a\?a # 4-8位 ?a 用所有字符进行破解
                # hashcat -a 3 -m 11600  $hash_save_path"/"$hashstrfilename --force --increment --increment-min 4 --increment-max 8 \?a\?a\?a\?a\?a\?a\?a\?a # 4-8位 ?a 用所有字符进行破解
                hashcat -a 3 -m 11600  $hash_save_path"/"$hashstrfilename --force --increment --increment-min 4 --increment-max 8 -1 \?u\?l\?d  \?1\?1\?1\?1\?1\?1\?1\?1 # 4-8位 ?a 用所有字符进行破解
              ;;
          *.zip) filepath=$1
                echo "[INFO] filepath $filepath"
                filename="$(echo $filepath |  awk -F'.zip' '{print $1}' | awk -F"/" ' {print $NF}')" # 其中， -F"/" 表示使用 / 作为分隔符， $NF 表示输出最后一个部分。
                echo "[INFO] filename = $filename"
                hashstrfilename=$filename"-zip_hash.txt"
                echo "[INFO] hashstrfilename = $hashstrfilename"
                hashstrfilenameorigin=$filename"-zip_hash_origin.txt"
                echo "[INFO] hashstrfilenameorigin = $hashstrfilenameorigin"
                # # 执行命令 生成hash文件
                cmdStr="zip2john  $filepath > $hash_save_path/$hashstrfilenameorigin"
                echo "[INFO] $cmdStr"
                zip2john  $filepath > $hash_save_path"/"$hashstrfilenameorigin
                # 读取处理
                john_hash_res=`cat $hash_save_path"/"$hashstrfilenameorigin`
                echo "[INFO] $john_hash_res"
                hash_str="$(echo $john_hash_res |  awk -F':' '{print $2}')"
                echo "[INFO] $hash_str"
                echo $hash_str > $hash_save_path"/"$hashstrfilename
                # 进行破解 
                # 17200 PKZIP (Compressed)                         $pkzip2$1*1*2*0*
                # 17210 PKZIP (Uncompressed)                       $pkzip2$1*1*2*0*
                # 17220 PKZIP (Compressed Multi-File)              $pkzip2$3*1*1*0*8*24
                # 17225 PKZIP (Mixed Multi-File)                   $pkzip2$3*1*1*0*0*24*
                # 17230 PKZIP (Mixed Multi-File Checksum-Only)     $pkzip2$8*1*1*0*8*24*a4
                hashcat -a 3 -m 17200 $hash_save_path"/"$hashstrfilename --force --increment --increment-min 4 --increment-max 8 -1 \?u\?l\?d  \?1\?1\?1\?1\?1\?1\?1\?1 # 4-8位 ?a 用所有字符进行破解
              ;;
          *.rar) filepath=$1
                echo "[INFO] filepath $filepath"
                filename="$(echo $filepath |  awk -F'.rar' '{print $1}' | awk -F"/" ' {print $NF}')" # 其中， -F"/" 表示使用 / 作为分隔符， $NF 表示输出最后一个部分。
                echo "[INFO] filename = $filename"
                hashstrfilename=$filename"-rar_hash.txt"
                echo "[INFO] hashstrfilename = $hashstrfilename"
                hashstrfilenameorigin=$filename"-rar_hash_origin.txt"
                echo "[INFO] hashstrfilenameorigin = $hashstrfilenameorigin"
                # # 执行命令 生成hash文件
                cmdStr="rar2john  $filepath > $hash_save_path/$hashstrfilenameorigin"
                echo "[INFO] $cmdStr"
                rar2john  $filepath > $hash_save_path"/"$hashstrfilenameorigin
                # 读取处理
                john_hash_res=`cat $hash_save_path"/"$hashstrfilenameorigin`
                echo "[INFO] $john_hash_res"
                hash_str="$(echo $john_hash_res |  awk -F':' '{print $2}')"
                echo "[INFO] $hash_str"
                echo $hash_str > $hash_save_path"/"$hashstrfilename
                # 进行破解
                hashcat -a 3 -m 13000  $hash_save_path"/"$hashstrfilename --force --increment --increment-min 4 --increment-max 8 -1 \?u\?l\?d  \?1\?1\?1\?1\?1\?1\?1\?1 # 4-8位 ?a 用所有字符进行破解
              ;;
          *) echo "[INFO] 不是 .7z、.zip、rar 文件";;
      esac
      echo "[INFO] Over ."
  else
      echo "[INFO] 没有安装或配置好 hashcat、john "
  fi
}


# [Linux 中三个下载工具-wget curl axel - 知乎](https://zhuanlan.zhihu.com/p/451426230)
# axel -n 16 -k  http://xxxxx

# 清除当前目录及所有子目录所有 ._*文件 、.~*文件、~*文件、.DS_Store文件
# [shell编程之如何遍历进入当前目录下的所有子目录 - Goalkeeper - 博客园](https://www.cnblogs.com/liuokay/archive/2011/08/15/2139493.html)
# function getAllFiles()
# {
#   FilePath=$1
#   fileList=`ls $FilePath`;
#   for fileName in $fileList;
#   do
#      #if test -f $fileName; then
#      if [ -f $fileName ];then
#         echo $fileName;
#      elif test -d $fileName; then
#         cd $fileName;
#         FilePath=`pwd`;
#         getAllFiles;
#         cd ..;
#      else
#         echo "$FilePath is a invalid path";
#      fi
#   done
# }

clearHomebrew(){
  # brew cleanup 工具来回收空间，但它默认只会清理 120 天以前的下载缓存
  # 注意的是删除的顺序，必须先处理原始文件、再处理软链接，软链接被删除后将无法定位到原始文件
  # [从零开始，编写一个 HomeBrew 缓存清理脚本 - 少数派](https://sspai.com/post/65842#!)
  echo "=== 开始清理Homebrew的缓存 ==="
  # 文件计数
  file_count=0
  link_count=0
  incomplete_count=0

  echo "=== 清理 HomeBrew Cask 下载缓存 ==="
  for cask_link in $(find ~/Library/Caches/Homebrew/Cask -type l)
  do
      # 将 Cask 软件包移至废纸篓
      # let file_count++
      # trash $(realpath $cask_link)
      let link_count++
      rm $link
  done

  echo "===  清理 HomeBrew 下载缓存 ==="
  for link in $(find ~/Library/Caches/Homebrew -type l)
  do
      let file_count++
      trash $(realpath $link)
      let link_count++
      rm $link
  done

  echo "===  清理 HomeBrew 清理未完成的下载*.incomplete文件 ==="
  # 获取 *.incomplete 文件数量
  let incomplete_count=$(ls -l ~/Library/Caches/Homebrew/downloads/*.incomplete | wc -l)
  # 清理未完成的下载
  rm ~/Library/Caches/Homebrew/downloads/*.incomplete

  # 复数输出函数
  plural() {
      if [ $1 -gt 1 ]
      then
          echo "$1 $2s"
      else
          echo "$1 $2"
      fi
  }

  # 输出消息提示
  echo "Pruned $(plural $link_count "symbolic link"), $(plural $file_count "file") and $(plural $incomplete_count "incomplete download") from $(realpath ~/Library/Caches/Homebrew)"

  # 调用 `brew cleanup`
  echo 'Running `brew cleanup`'
  brew cleanup
}

clearLog(){
  # clear_root_dir=$1
  # 判断是否为空
  clear_root_dir=$1
  if [ ! -n "$clear_root_dir" ] ;then
    echo "[INFO] $clear_root_dir is empty."
    echo "[INFO] 正在查找一些目录下的 *.log 文件和日志文件删除..."
    # find $clear_root_dir -name '*.log' -print -exec rm -fr {} \;
    rm -r "$HOME/.local/bin/Log"
    # rm -r "$HOME/Library/Cache/Sublime Merge"
    # rm -r "$HOME/Library/Cache/Sublime Text"


    # Dock程序右键上的记录
    # 打开Finder，按住Option点击 前往 ，打开 资源库（~/Library/）。在搜索框中搜索：lsshare，并将搜索结果定位到“资源库”。

    # rm  "$HOME/Library/Application Support/Sublime Text/Local/*"
    # rm  "$HOME/Library/Application\ Support/Sublime\ Text/Local/Auto\ Save\ Session.sublime_session"
    # rm  "$HOME/Library/Application\ Support/Sublime\ Text/Local/Session.sublime_session"

    rm ~/Library/Application\ Support/Sublime\ Text/Local/Auto\ Save\ Session.sublime_session
    rm ~/Library/Application\ Support/Sublime\ Text/Local/Session.sublime_session

    # [从零开始，编写一个 HomeBrew 缓存清理脚本 - 少数派](https://sspai.com/post/65842#!)
    # clearHomebrew

    # 其他
    # - Beyond Compare 使用时间数据
    rm "$HOME/Library/Application Support/Beyond Compare/registry.dat"

    # 
    # rm /var/log
    find "$HOME/Documents" -name '*.log$' -print -exec rm -fr {} \;
    find "$HOME/Documents/XWorkSpaces" -name '*.log$' -print -exec rm -fr {} \;
    find "$HOME/Downloads" -name '*.log$' -print -exec rm -fr {} \;
    echo "[INFO] 查找删除完结."
  else
    echo "[Debug] the clear_root_dir is not empty."
    if [ -d $clear_root_dir ]; then
      echo "[INFO] 存在 $clear_root_dir 目录."
      echo "[INFO] 正在查找 $clear_root_dir 该目录下的 *.log 文件删除..."
      find $clear_root_dir -name '*.log$' -print -exec rm -fr {} \;
      clearDS_Store $clear_root_dir
      # echo "[INFO] 查找删除完结."
    else
      echo "[INFO] 不存在 $clear_root_dir 目录地址."
    fi
  fi
}

clearDS_Store(){
  clear_root_dir=$1
  if [ ! -n "$clear_root_dir" ] ;then
    echo "[INFO] \$1 is empty."
    clear_root_dir="./"
  fi

  if [ -d $clear_root_dir ]; then
    echo "[INFO] 存在 $clear_root_dir 目录."
    # find ./ -maxdepth 1 -type d -empty                     # 找出当前目录下空文件夹
    # find ./ -maxdepth 1 -type d -empty -exec rm -rf {} \;  # 删除当前目录空文件夹

    # find ./ -name ".DS_Store" -depth -exec rm {} \ ;  # 
    # find ./ -maxdepth 1 -type d -empty                     # 找出当前目录下空文件夹
    # find ./ -maxdepth 1 -type d -empty -exec rm -rf {} \;  # 删除当前目录空文件夹
    # find ./ -name 'index.cdif' -exec rm -f {} \;   # 找出当前目录下index.cdif删除
    # find ./ -name "[0-9][0-9][0-9]_*.json"  -exec mv  {}  ~/Desktop/t \; # 找出当前目录下 匹配的文件移动的  ~/Desktop/t 文件夹中

    # find ./ -name "*.DS_Store" -print -exec rm -fr {} \;
    # find ./ -regex '.*\.AppleDouble\|.*\.DS_Store\|.*\.project\|.*\.settings' -print rm -fr {} \;
    # 注：.DS_Store (英文全称 Desktop Services Store)[1] 是一种由苹果公司的Mac OS X操作系统所创造的隐藏文件，目的在于存贮文件夹的自定义属性，例如文件们的图标位置或者是背景色的选择。
    echo "[INFO] 正在查找 $clear_root_dir 该目录下的 .DS_Store、._*、.~*、*.swap文件删除..."
    find $clear_root_dir -name '^.DS_Store$' -print -exec rm -fr {} \;
    find $clear_root_dir -name '^._*' -print -exec rm -fr {} \;
    find $clear_root_dir -name '^.~*' -print -exec rm -fr {} \;
    find $clear_root_dir -name '^～*' -print -exec rm -fr {} \;
    find $clear_root_dir -name '^~*' -print -exec rm -fr {} \;
    find $clear_root_dir -name '^.*.swap$' -print -exec rm -fr {} \; # 删除vim交换缓存文件
    find $clear_root_dir -name '*.swap$' -print -exec rm -fr {} \; # 删除vim交换缓存文件
    echo "[INFO] 查找删除完结."
  else
    echo "[INFO] 不存在 $clear_root_dir 目录."
  fi
}

init_setting_ssh_git_gpg(){
  # ssh
  chmod 755 ~/.ssh
  chmod 700 ~/.ssh/config
  chmod 600 ~/.ssh/id_rsa*
  chmod 644 ~/.ssh/id_rsa_*.pub

  # gpg: WARNING: unsafe permissions on homedir '/Users/tom/.gnupg'
  # 停止dirmngr
  # sudo gpgconf--kill dirmngr
  # sudo仅此一次，因为dirmngr是以root身份运行的，其套接字可以证明这一点），然后恢复您的所有权：
  # sudo chown -R $USER ~/.gnupg

  # 
  git config --global core.quotepath false  
  git config --global gui.encoding utf-8  
  git config --global i18n.commit.encoding utf-8  
  git config --global i18n.logoutputencoding utf-8  
  
}

localhost-restart() { 
  sudo dscacheutil -flushcache; 
  sudo killall -HUP mDNSResponder 
}

host-update() {
  ~/.config/scripts/githubhost.sh -u ;
  echo "[INFO] 刷新 DNS; macOS 执行命令：sudo killall -HUP mDNSResponder"
  sudo killall -HUP mDNSResponder
}

# alias host-update='~/.config/scripts/githubhost.sh -u'
# 大部分情况下是直接生效，如未生效可尝试下面的办法，刷新 DNS： sudo killall -HUP mDNSResponder


# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$($HOME'/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then
        . "$HOME/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="$HOME/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# Anaconda安装的包所在默认的位置
# anaconda安装的位置\envs\虚拟环境\Lib\site-packages
# 例：（base） ~/anaconda3/envs/py310/lib
#             ~/anaconda3/lib/python3.11/site-packages

# <<< conda initialize <<<



# 工具
# 配置 rsync + inotify 实时同步
# [使用rsync+inotify实现触发式实时文件同步](https://mp.weixin.qq.com/s/TUeTk8ronLBIAuKYYcQJig)
auto-rsync(){ # 递归监视目录及其子目录,触发式实时文件同
  local_target_workspace_path=$1
  remote_target_workspace_path=$2
  while fswatch -o  $local_target_workspace_path ;do    # 当接收到有关对该目录的任何更改的事件时，
    # rsync -avz /data/ root@172.16.5.222:/opt/data/ 
    rsync -avz $local_target_workspace_path $remote_target_workspace_path 
  done 

  # 目标为远程服务器时，需要生成SSH密钥对并上传公钥（在服务端生成SSH密钥对，并将公钥上传到客户端，以便实现无密码的SSH连接。）

}

kill-auto-rsync(){ # 发现并杀死同步进程
    # 获取全部的java程序的进程号全部关闭  
    pid=`ps -ef | grep "xxx-platform-sso-1.0-SNAPSHOT" | grep -v grep | awk '{print $2}'`  
    kill -9 $pid  

    ps -aux|grep java | grep -v grep  

    echo "停止成功"  
}

kill-all-java(){
    date  
    # 获取全部的java程序信息  
    ps -aux|grep java | grep -v grep  

    # 获取全部的java程序的进程号  
    pids=$(ps -ef | grep java | grep -v grep  | awk '{print $2}')  

    # 循环一个个关闭  
    for pid in $pids  
    do  
     echo  $pid  
     kill -9  $pid  
    done  

    echo "执行完毕"  
}
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
export PATH="$PYENV_ROOT/shims:$PATH"
# eval "$(pyenv init -)"
# export PYENV_ROOR="$HOME/.pyenv"
# export PATH=$PYENV_ROOT/shims:$PATH
# eval "$(pyenv init -)"
# eval "$(pyenv virtualenv-init -)"
